package org.gateway.service;


import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.gateway.router.GatewayRouteDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.List;
import java.util.concurrent.Executor;

@Service
@Slf4j
public class DynamicRouteService {

    private static final String ROUTES_DATA_ID = "gateway-routes.yaml";
    private static final String ROUTES_GROUP = "DEFAULT_GROUP";



    @Autowired
    private NacosConfigManager nacosConfigManager;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    @Autowired
    private RouteDefinitionLocator routeDefinitionLocator;

    @Autowired
    private ApplicationEventPublisher eventPublisher;



    @PostConstruct
    public void init() throws NacosException {
        // 1. 初始化加载路由配置
        refreshRoutes();

        // 2. 添加Nacos监听器
        addNacosListener();
    }

    private void addNacosListener() {
        try {
            nacosConfigManager.getConfigService().addListener(ROUTES_DATA_ID, ROUTES_GROUP, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("检测到路由配置变更: {}", configInfo);
                    refreshRoutes();
                }
            });
        } catch (NacosException e) {
            log.error("添加Nacos监听器失败", e);
        }
    }

    public void refreshRoutes() {
        try {
            String configInfo = nacosConfigManager.getConfigService().getConfig(ROUTES_DATA_ID, ROUTES_GROUP, 5000);
            log.info("从Nacos获取路由配置: \n{}", configInfo);
            updateRoutes(configInfo);
        } catch (NacosException e) {
            log.error("从Nacos获取路由配置失败", e);
        }
    }

    private void updateRoutes(String config) {
        // 1. 清空现有路由
        routeDefinitionLocator.getRouteDefinitions()
                .flatMap(route -> routeDefinitionWriter.delete(Mono.just(route.getId())))
                .subscribe();

        // 2. 解析并添加新路由,从json转成RouteDefinition
        List<GatewayRouteDefinition> routeDefinitions = JSON.parseArray(config, GatewayRouteDefinition.class);

        System.out.println("路由另一信息:"+routeDefinitions);

        for (GatewayRouteDefinition grd : routeDefinitions) {
            RouteDefinition routeDefinition = new RouteDefinition();
            routeDefinition.setId(grd.getId());
            routeDefinition.setUri(URI.create(grd.getUri()));
            routeDefinition.setOrder(grd.getOrder());

            // 设置断言
            grd.getPredicates().forEach(predicate -> {
                String[] parts = predicate.split("=", 2);
                if (parts.length == 2) {
                    routeDefinition.getPredicates().add(
                            new PredicateDefinition(parts[0] + "=" + parts[1])
                    );
                }
            });

            // 设置过滤器
            grd.getFilters().forEach(filter -> {
                String[] parts = filter.split("=", 2);
                if (parts.length == 2) {
                    routeDefinition.getFilters().add(
                            new FilterDefinition(parts[0] + "=" + parts[1])
                    );
                }
            });

            // 添加路由
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        }

        // 3. 发布事件刷新路由
        eventPublisher.publishEvent(new RefreshRoutesEvent(this));
        ;
        log.info("路由配置刷新完成，共加载 {} 条路由规则", routeDefinitions.size());
    }
}
